#ifndef _DES_H_
#define _DES_H_
#include "padding.h"
/**
 * DES的密钥长64位
 * DES的加密过程：我们输入明文，DES会把明文分组，每组64bits，然后DES算法对每个明文块进行处理，
 * 得到64bits的密文，再将所有密文块拼接就成为了密文
 * 3DES（或称为Triple DES），它相当于是对每个数据块应用三次DES加密算法。3*8字节密钥。
 */

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

#include <stdint.h>

#define DES_BLOCK_LEN 		8       // 8bytes

//加解密模式
typedef enum {
    DES_MODE_ECB = 0,   // 电子密码本模式
    DES_MODE_CBC = 1,   // 密码块连接模式
    DES_MODE_CFB = 2,   // 密文反馈模式 
    DES_MODE_OFB = 3,   // 输出反馈模式 
    DES_MODE_CTR = 4,   // 计数器模式   
} DESMode_t;

//密匙长度
typedef enum{
    DES_KEY_LEN_8 = 8,      // key-length: 8bytes  -> single DES
    DES_KEY_LEN_16 = 16,    // key-length: 16bytes -> triple DES (key1=key[0], key2=key[8], key3=key[0])
    DES_KEY_LEN_24 = 24,    // key-length: 24bytes -> triple DES (key1=key[0], key2=key[8], key3=key[16])
}DESKeyLen_t;

/**
 * \brief          DES context structure
 */
typedef struct
{
    int mode;                   /* 加密模式 关联 DESMode_t*/
    int padding;                /* 填充方式 关联 DESPadding_t */
    int key_len;                /* 密匙长度 关联 DESKeyLen_t */
    unsigned char iv[16];       /* 初始化向量 */
    unsigned char key[DES_KEY_LEN_24];          /* DES密匙 当密匙长度为64bit时，使用des加解密。当使用28bit或192bit时，使用3des加解密 */
    void (*ctr_alg)(void *Nonce, int counter);  /* 计数器模式下使用的算法 */
}DES_context;

/**
 * @brief des init function
 * 
 * @param ctx DES context
 * @param mode DES encrypt/decrypt mode
 * @param padding DES filling type
 * @param key_len key data length
 * @param key key data
 * @param iv DES iv, it must be 16 bytes data
 * @param alg when mode=DES_MODE_CTR , it will use this personal algorithm
 */
void des_init(DES_context *ctx, DESMode_t mode, padding_t padding, DESKeyLen_t key_len, unsigned char* key, unsigned char iv[16], void (*alg)(void*,int));

/**
 * @brief DES encrypt function
 * 
 * @param ctx DES context
 * @param input the data that need to be encrypt
 * @param length input data length
 * @param output output the encrypted data, it need at least length+16 bytes size
 * @return int - output data length, return 0 means fail
 */
int des_encrypt(DES_context *ctx, unsigned char *input, int length, unsigned char *output);

/**
 * @brief DES decrypt function
 * 
 * @param ctx DES context
 * @param input  input the data that need to be decrypt
 * @param length input data length
 * @param output output output the decrypted data, it need at least length bytes size
 * @return int - output data length, return 0 means fail
 */
int des_decrypt(DES_context *ctx, unsigned char *input, int length, unsigned char *output);


#ifdef __cplusplus
}
#endif /* __cplusplus */

#endif /* _DES_H_ */
